<template>
	<el-dialog v-model="visible" :title="title || $t('settings.Clipper')" width="650px" center :destroy-on-close="true">
		<div id="dropzone" class="croppers-container" v-loading="dataloading">
			<div class="img-cropper" :style="{'opacity': dataloading ? '0' : '1'}">
				<img ref="imgRef" :src="cropperImg" />
			</div>
			<!-- <div class="img-preview"></div> -->
			<div v-if="!cropperImgStart" class="no-img">{{ $t('settings.SelectImg') }}</div>
		</div>
		<div style="margin-top: 20px" class="flex flexC opa-box" v-if="cropperImgStart">
			<el-button @click="opaimg('1')" :icon="ZoomIn" />
			<el-button @click="opaimg('2')" :icon="ZoomOut" />
			<el-button @click="opaimg('3')" :icon="RefreshRight" />
			<el-button @click="opaimg('4')" :icon="RefreshLeft" />
			<el-button @click="opaimg('5')" :icon="Refresh" />
		</div>
		<div style="margin-top: 20px" class="flex flexC">
			<el-button type="primary" @click="handleUpload">{{ $t('settings.SelectImg') }}</el-button>
			<el-button type="primary" @click="handleDownload" :loading="btnloading">{{ $t('settings.Confirmupload') }}</el-button>
			<input ref="fileRef" style="display: none" type="file" accept="image/*" @change="handleFileChange" />
		</div>
	</el-dialog>
</template>
<script lang="ts" setup>
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
import { nextTick, ref } from 'vue'
import { postApi } from '@/api/api'
import { BASS_UPLOADURL } from '@/config/index'
import { ElMessage } from 'element-plus/es'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
import {
  RefreshLeft,
  RefreshRight,
  Refresh,
  ZoomOut,
  ZoomIn,
} from '@element-plus/icons-vue'
const prop = defineProps({
	title: {
		type: String,
		default: ''
	},
	cropBoxResizable: {
		type: Boolean,
		default: true
	},
	aspectRatio: {
		type: Number,
		default: 1
	},
	maxSize: { // 单位MB
		type: Number,
		default: 10
	}
})
const emit = defineEmits(['upload'])
const visible = ref(false)
const btnloading = ref(false)
const dataloading = ref(false)
const imgRef = ref()
const cropperImg = ref('')
const cropperImgStart = ref('')
const fileRef = ref()
const cropper = ref<any>(null)
const dropzone: any = ref(null)

// 打开
const openDialog = (img: any) => {
	if (img) {
		// const base64img = await setAvatarBase64(img)
    cropperImg.value = img
		cropperImgStart.value = img
	} else {
		cropperImg.value = ''
		cropperImgStart.value = ''
	}
	visible.value = true
	nextTick(() => {
		initCropper()
	})
}
// 带文件打开
const openDialogFile = (file: any) => {
	cropperImg.value = ''
	cropperImgStart.value = ''
	visible.value = true
	nextTick(() => {
		initCropper(true, file)
	})
}
const dragEnterHandler = (e: any) => {
	e.preventDefault(); // 在拖动元素进入指定区域时，取消默认行为，并添加视觉效果(例如改变背景色)
	dropzone.value.style.backgroundColor = '#f2f2f2';
}
const dragOverHandler = (e: any) => {
	e.preventDefault(); // 在拖动元素在指定区域内移动时，同样取消默认行为
}
const dragLeaveHandler = (e: any) => {
	// 在拖动元素离开指定区域时，移除视觉效果
	dropzone.value.style.backgroundColor = '';
}
const dropHandler = (e: any) => {
	e.preventDefault();
	// 在拖动元素释放时，取消默认行为，获取拖动的文件列表
	const files = e.dataTransfer.files;
	// 进行文件上传等后续操作
	replaceFile(files[0])
	// 恢复默认视觉效果
	dropzone.value.style.backgroundColor = '';
}
// 将转换成base64的图片设置成可跨域
const setAvatarBase64 = (src: any) => {
	return new Promise((resolve, reject) => {
			let image = new Image();
			// 处理缓存
			image.src = src + "?v=" + Math.random();
			// 支持跨域图片
			image.crossOrigin = "*";
			image.onload = () => {
					let base64 = transBase64FromImage(image);
					resolve(base64);
			};
	});
}
//将图片转换成base64
const transBase64FromImage = (image: any) => {
    console.log("image", image);
    let canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    let ctx: any = canvas.getContext("2d");
    ctx.drawImage(image, 0, 0, image.width, image.height);
    // // 可选其他值 image/jpeg
    return canvas.toDataURL("image/png");
}
/**
 * element:  需要裁剪的图片元素，一般指本地获取到的img展示标签
options: {
	aspectRatio: 1 / 1, // 裁剪框纵横尺寸比例
	autoCropArea: 1,  // 它应该是一个介于 0 和 1 之间的数字。定义自动裁剪区域大小（百分比）, 默认80%
	viewMode: 1,  // 视图模式
	dragMode: "move", // 图片可移动 拖拽模式
	cropBoxMovable:false, //是否可以拖拽裁剪框
	preview：ele，// Dom元素，该元素的预览尺寸样式尽量和aspectRatio尺寸比例保持一致
	responsive： true, // 调整窗口大小时重新渲染裁剪器
	modal:  true,// 在图像上方和裁剪框下方显示黑色模态
	rotatable:  true,// 启用以旋转图像
	scalable: true, // 启用以缩放图像
	zoomable:  true,// 启用以缩放图像
	zoomOnTouch: true,  // 启用通过拖动触摸来缩放图像
	zoomOnWheel: true, //鼠标滚轮缩放
	cropBoxMovable: false, // 裁剪框可移动
	cropBoxResizable: false, // 裁剪框大小可调整
	resizable: false, // 是否允许改变裁剪框大小
	ready: Function,  // 裁剪实例准备完成回调,由于加载图片时有一个异步过程，所以大部分方法都应该在 ready 之后调用
	reset: Function,  // reset() 重置
	clear: Function,  // clear() 清除
	replace(url, hasSameSize): Function,  // url 图片地址， hasSameSize：Boolean,如果新图像与旧图像大小相同，则不会重建裁剪器，只会更新所有相关图像的 URL。这可用于应用过滤器
	...
}

 */
const initCropper = (isFile: any = false, file: any = null) => {
	if (cropperImg.value) {
		dataloading.value = true
	}
	cropper.value = new Cropper(imgRef.value, {
		viewMode: 1,
		// dragMode: 'none',
		dragMode: 'move',
		initialAspectRatio: 1,
		background: true,
		rotatable: true,
		autoCropArea: 1,
		cropBoxResizable: prop.cropBoxResizable,
		aspectRatio: prop.aspectRatio,
		ready: () => {
			console.log('图片初始化完成')
			dataloading.value = false
		}
		// preview: '.img-preview'
	})
	if (isFile) {
		console.log(file);
		replaceFile(file)
	}
	dropzone.value = document.getElementById('dropzone');
	dropzone.value.addEventListener('dragenter', dragEnterHandler);
	dropzone.value.addEventListener('dragover', dragOverHandler);
	dropzone.value.addEventListener('dragleave', dragLeaveHandler);
	dropzone.value.addEventListener('drop', dropHandler);
}
// 操作图片
const opaimg = (type: any) => {
	if (type == 1) {
		// 放大
		cropper.value.zoom(0.1)
	} else if (type == 2) {
		// 缩小
		cropper.value.zoom(-0.1)
	} else if (type == 3) {
		// 右转
		cropper.value.rotate(90)
	} else if (type == 4) {
		// 左转
		cropper.value.rotate(-90)
	} else if (type == 5) {
		// 重置
		cropper.value.reset()
	}
}
const handleUpload = () => {
	fileRef.value.click()
}

const handleFileChange = (e: any) => {
	const file = e.target.files[0]
	replaceFile(file)
}
const replaceFile = (file: any) => {
	const isLt2M = file.size / 1024 / 1024 < prop.maxSize
	if (!isLt2M) {
		ElMessage.error(`上传图片大小不能超过 ${prop.maxSize}MB!`)
		return
	}
	cropperImgStart.value = '1'
	const URL = window.URL || window.webkitURL
	cropper.value.replace(URL.createObjectURL(file))
}
const randomString = (len: any) => {
	var len = len || 16
	var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
	var maxPos = chars.length
	var pwd = ''
	for (let i = 0; i < len; i++) {
		pwd += chars.charAt(Math.floor(Math.random() * maxPos))
	}
	return pwd + '.png'
}
const handleDownload = () => {
	cropper.value.getCroppedCanvas().toBlob(function (blob: any) {
		btnloading.value = true
		// 上传文件
		const file = new window.File([blob], randomString(16), {
			type: 'image/png'
		})
		const formData = new FormData()
		formData.append('file', file)
		postApi(BASS_UPLOADURL, formData, t('axios.Uploading'))
			.then((res: any) => {
				btnloading.value = false
				if (res.code == 200) {
					visible.value = false
					emit('upload', res.data)
				} else {
					ElMessage.error(res.message || res.data || t('opaError'))
				}
			})
			.catch((err: any) => {
				btnloading.value = false
				console.log(err)
			})
		// const link = document.createElement('a')
		// link.href = URL.createObjectURL(blob)
		// link.setAttribute('download', '')
		// document.body.appendChild(link)

		// // 模拟点击下载
		// link.click()
		// document.body.removeChild(link)
	})
	cropper.value.crop()
}

defineExpose({
	openDialog,
	openDialogFile
})
</script>

<style scoped lang="scss">
.croppers-container {
	display: flex;
	justify-items: center;
}
.opa-box{
	:deep(){
		.el-icon{
			font-size: 19px;
		}
	}
}
.img-cropper {
	width: 600px;
	height: 400px;
	img{
		max-width: 100%;
		max-height: 100%;
	}
}
.img-preview {
	width: 400px;
	height: 400px;
	overflow: hidden;
	margin: auto;
}
.no-img {
	position: absolute;
	width: 600px;
	height: 400px;
	display: flex;
	justify-content: center;
	align-items: center;
	color: #999;
	font-size: 24px;
}
</style>
